package com.zmn.plat.business.impl.expressage;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.zmn.framework.core.http.HttpClientsFactory;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.plat.business.interfaces.expressage.ExpressageException;
import com.zmn.plat.business.interfaces.expressage.ExpressageService;
import com.zmn.plat.constant.MessageQueueConstant;
import com.zmn.plat.model.dto.expressage.ExpressageCompanyDTO;
import com.zmn.plat.model.dto.expressage.ExpressageDTO;
import com.zmn.plat.services.config.KuaiDi100Config;

/**
 * 快递100实现
 *
 * @author quanjic
 * @version v1.0
 * @since 2018/11/27 10:05
 **/
@CacheConfig(cacheNames = "redis5m")
@Deprecated
public class KuaiDi100ServiceImpl implements ExpressageService {

    @Value("${spring.mq.topic}")
    private String topic;

    private Logger logger = LoggerFactory.getLogger(KuaiDi100ServiceImpl.class);
    private KuaiDi100Config config;

    private Map<String, String> name2code = new ConcurrentHashMap<>();
    private Map<String, String> code2name = new ConcurrentHashMap<>();

    @Autowired
    private ZmnMQSender zmnMQSender;

    @PostConstruct
    public void init() {
        try (InputStream inputStream = this.getClass().getResourceAsStream("/expressage_code")) {
            logger.info("#expressage# loading company code...");
            List<String> lines = IOUtils.readLines(inputStream, "UTF-8");
            String[] array = null;
            for (String line : lines) {
                if (StringUtils.isEmpty(line)) {
                    continue;
                }
                array = line.split(";");
                if (array.length != 2) {
                    logger.info("#expressage# continue: {}", line);
                    continue;
                }
                name2code.put(array[0], array[1]);
                code2name.put(array[1], array[0]);
            }
            logger.info("#expressage# loaded company code number: {}", name2code.size());
        } catch (Exception e) {
            logger.error("#expressage# loading company code fail", e);
            throw new ExpressageException(e);
        }

    }

    @Override
    @Cacheable(key = "'express:' + #p0 + ':' + #p1")
    public ExpressageDTO find(String company, String code) {

        if (StringUtils.isEmpty(company)) {
            throw new NullPointerException("null company");
        }
        if (StringUtils.isEmpty(code)) {
            throw new NullPointerException("null code");
        }

        String url = null;
        HashMap params = null;
        String response = null;
        try {
            JSONObject paramJsonObject = new JSONObject(true);
            paramJsonObject.put("com", company);
            paramJsonObject.put("num", code);
            String param = paramJsonObject.toJSONString();
            String sign = DigestUtils.md5Hex(param + config.getKey() + config.getCustomer()).toUpperCase();

            url = config.getUrl() + "/poll/query.do";
            params = new HashMap();
            params.put("param", param);
            params.put("sign", sign);
            params.put("customer", config.getCustomer());
            response = HttpClientsFactory.getHttpClients().postForm(url, params);
            if (StringUtils.isEmpty(response)) {
                throw new ExpressageException();
            }

            ExpressageDTO expressageDO = KuaiDi100Utils.parse(JSON.parseObject(response));
            logger.info("#expressage#find url:{}, request:{}, response:{}", url, params, response);

            return expressageDO;
        } catch (ExpressageException e) {
            logger.error("#expressage#find url:{}, request:{}, response:{}", url, params, response, e);
            throw e;
        } catch (Exception e) {
            logger.error("#expressage#find url:{}, request:{}, response:{}", url, params, response, e);
            throw new ExpressageException(e);
        }
    }

    @Override
    @Cacheable(key = "'express:company_list:' + #p0")
    public List<ExpressageCompanyDTO> findCompany(String code) {

        String url = null;
        String response = null;
        try {
            List<ExpressageCompanyDTO> result = Collections.EMPTY_LIST;
            url = config.getAutoNumberUrl() + "?num=" + code + "&key=" + config.getKey();
            response = HttpClientsFactory.getHttpClients().get(url);
            if (StringUtils.isEmpty(response)) {
                throw new ExpressageException();
            }
            JSONArray jsonArray = JSON.parseArray(response);
            if (jsonArray != null) {
                result = new ArrayList<>(jsonArray.size());
                for (int i = 0; i < jsonArray.size(); i++) {
                    String comCode = jsonArray.getJSONObject(i).getString("comCode");
                    if (StringUtils.isNotEmpty(comCode)) {
                        result.add(new ExpressageCompanyDTO(code2name.get(comCode), comCode));
                    }
                }
            }
            logger.info("#expressage#findCompany url:{}, response:{}", url, response);
            return result;
        } catch (ExpressageException e) {
            logger.error("#expressage#find url:{}, response:{}", url, response, e);
            throw e;
        } catch (Exception e) {
            logger.error("#expressage#find url:{},  response:{}", url, response, e);
            throw new ExpressageException(e);
        }
    }

    @Override
    public List<ExpressageCompanyDTO> listCompany() {
        List<ExpressageCompanyDTO> result = new ArrayList<>(name2code.size());
        for (Map.Entry<String, String> entry : name2code.entrySet()) {
            result.add(new ExpressageCompanyDTO(entry.getKey(), entry.getValue()));
        }
        return result;
    }

    /**
     * 订阅快递单号；获取快递最新消息
     *
     * @param company
     *            快递公司编码，可为空
     * @param code
     *            快递单号
     * @throws ExpressageException
     */
    @Override
    public void subscribe(String company, String code) throws ExpressageException {

        if (StringUtils.isEmpty(code)) {
            throw new NullPointerException("null code");
        }

        String url = null;
        Map<String, String> params = null;
        String response = null;
        try {
            JSONObject paramObj = new JSONObject();
            // key
            paramObj.put("key", config.getKey());
            paramObj.put("company", company);
            paramObj.put("number", code);

            Map<String, String> parameters = new HashMap<>();
            // 回调URL
            parameters.put("callbackurl", config.getCallbackUrl());
            // 1:智能判断单号所属公司的功能
            parameters.put("autoCom", "1");

            paramObj.put("parameters", parameters);

            params = Maps.newHashMap();
            params.put("schema", "json");
            params.put("param", paramObj.toJSONString());
            url = config.getUrl() + "/poll";
            response = HttpClientsFactory.getHttpClients().postForm(url, params);
            if (StringUtils.isEmpty(response)) {
                throw new ExpressageException();
            }
            JSONObject responseObj = JSON.parseObject(response);
            if (responseObj == null || !"200".equalsIgnoreCase(responseObj.getString("returnCode"))) {
                throw new ExpressageException(responseObj != null ? responseObj.getString("message") : "");
            }
            logger.info("#expressage#subscribe url:{}, request:{}, response:{}", url, params, response);
        } catch (ExpressageException e) {
            logger.error("#expressage#subscribe url:{}, request:{}, response:{}", url, params, response, e);
            throw e;
        } catch (Exception e) {
            logger.error("#expressage#subscribe url:{}, request:{}, response:{}", url, params, response, e);
            throw new ExpressageException(e);
        }

    }

    /**
     * @param content
     *            内容
     */
    public void callback(String content) {
        if (StringUtils.isEmpty(content)) {
            throw new NullPointerException("null content");
        }
        JSONObject jsonObject = JSON.parseObject(content);
        JSONObject last = jsonObject.getJSONObject("lastResult");
        ExpressageDTO expressageDO = KuaiDi100Utils.parse(last);
        if (expressageDO != null) {
            zmnMQSender.send(topic, MessageQueueConstant.TAGS_EXPRESSAGE_UPDATE, expressageDO.getCompany() + "_" + expressageDO.getCode(), JSON.toJSONString(expressageDO));
        }
    }

    public KuaiDi100Config getConfig() {
        return config;
    }

    public void setConfig(KuaiDi100Config config) {
        this.config = config;
    }
}
